package com.ssis.core;

import java.util.ArrayList;
import org.newdawn.slick.util.Log;
import com.ssis.core.Cell.CellType;

public class Station {
	private int xOffset;
	private int yOffset;
	private Cell[][] design;
	private static final int STATION_HEIGHT = 20;
	private static final int STATION_WIDTH = 20;
	private StationCursor cursor;
	private Cargo cargo;
	private ArrayList<Crew> crew;
	private ArrayList<Cell> cells;
	
	public Station() {
		design = new Cell[STATION_HEIGHT][STATION_WIDTH];
		cells = new ArrayList<Cell>();
		xOffset = (STATION_WIDTH*Cell.CELL_WIDTH - Game.WIDTH)/2;
		yOffset = (STATION_HEIGHT*Cell.CELL_WIDTH - Game.HEIGHT)/2;
		
		for(int i = 0; i < STATION_HEIGHT; i++) {
			for(int j = 0; j < STATION_WIDTH; j++) {
				design[i][j] = new Cell(CellType.EMPTY, i, j, xOffset, yOffset);
				cells.add(design[i][j]);
				//Log.debug("Created cell at " + i*Cell.CELL_WIDTH + ", " + j*Cell.CELL_WIDTH);
			}
		}
		
		// initial architecture
		int startx = STATION_WIDTH/2;
		int starty = STATION_HEIGHT/2;
		design[startx][starty].upgrade(CellType.CARGO);
		design[startx-1][starty].upgrade(CellType.DORM);
		design[startx][starty-1].upgrade(CellType.GENERATOR);
		design[startx-1][starty-1].upgrade(CellType.CAPACITOR);
		design[startx-2][starty-1].upgrade(CellType.OFFICE);
		
		this.cargo = new Cargo();
		this.crew = new ArrayList<Crew>();
		
		this.crew.add(new Crew());
		cursor = new StationCursor();
	}
	
	public void render() {
		for (Cell cell : cells)
			cell.render();
		cursor.render(xOffset, yOffset);
	}

	public void addCell() {
		this.addCell(Cell.CellType.FRAME, cursor.getX(), cursor.getY());
	}
	
	public void addCell(CellType type) {
		this.addCell(type, cursor.getX(), cursor.getY());
	}
	
	public void addCell(CellType type, int x, int y) {
		if (!canAfford(type))
			return;
		
		if (design[x][y].getType() == CellType.EMPTY) {
			if (!isBuildable(x,y))
				return;
	
			cargo.changeCredits(-10);
			cargo.changeEnergy(-10);
			design[x][y] = new Cell(type, x, y, xOffset, yOffset);
			cells.add(design[x][y]);
		} else {
			cargo.changeCredits(-5);
			cargo.changeEnergy(-5);
			design[x][y].upgrade(type);
		}
	}

	private boolean canAfford(CellType type) {
		if(cargo.getCredits() < 10)
			return false;
		if(cargo.getEnergy() < 10)
			return false;
		
		return true;
	}
	
	private boolean isBuildable(int x, int y) {
		if (x<0 || y<0 || x+1>STATION_WIDTH || y+1>STATION_HEIGHT)
			return false;
		
		if (!((x>0 && design[x-1][y].getType() != Cell.CellType.EMPTY) ||
				(x+1<STATION_WIDTH && design[x+1][y].getType() != Cell.CellType.EMPTY) ||
				(y>0 && design[x][y-1].getType() != Cell.CellType.EMPTY) ||
				(y+1<STATION_HEIGHT && design[x][y+1].getType() != Cell.CellType.EMPTY)))
			return false;
		
		return true;
	}
	
	public void moveCursor(int x, int y) {
		x+= xOffset;
		y+= yOffset;
		if(x < 0)
			x-=Cell.CELL_WIDTH;
		if(y < 0)
			y-=Cell.CELL_WIDTH;
		cursor.moveto(x / Cell.CELL_WIDTH, y / Cell.CELL_WIDTH);
	}
	
	public void resetPosition() {
		for (Cell cell : cells)
			cell.move(-xOffset, -yOffset);
		
		cursor.moveto(STATION_WIDTH/2, STATION_HEIGHT/2);
		xOffset = 0;
		yOffset = 0;
		
		move(-(STATION_WIDTH*Cell.CELL_WIDTH - Game.WIDTH)/2,-(STATION_HEIGHT*Cell.CELL_WIDTH - Game.HEIGHT)/2);
	}
	
	public void move(int x, int y) {
		xOffset -= x;
		yOffset -= y;
		int xOverpull = 0;
		int yOverpull = 0;
		Log.debug("Offsets " + xOffset + "," + yOffset);
		if (xOffset < 0) {
			xOverpull = -xOffset;
			xOffset = 0;
		}
		if (yOffset < 0) {
			yOverpull = -yOffset;
			yOffset = 0;
		}
		if (xOffset + Game.WIDTH > STATION_WIDTH*Cell.CELL_WIDTH) {
			Log.debug("Dragged too far!");
			xOverpull = (STATION_WIDTH*Cell.CELL_WIDTH - Game.WIDTH) - xOffset;
			xOffset = STATION_WIDTH*Cell.CELL_WIDTH - Game.WIDTH;
		}
		if (yOffset + Game.HEIGHT > STATION_HEIGHT*Cell.CELL_WIDTH) {
			Log.debug("Dragged too far!");
			yOverpull =  (STATION_HEIGHT*Cell.CELL_WIDTH - Game.HEIGHT) - yOffset;
			yOffset = STATION_HEIGHT*Cell.CELL_WIDTH - Game.HEIGHT;
		}

		for (Cell cell : cells)
			cell.move(xOverpull - x, yOverpull - y);
	}
	
	public Cargo cargo() {
		return cargo;
	}
	
	public void cycle() {
		for (Cell cell : cells) {
			cargo.changeCredits(cell.income());
			cargo.changeEnergy(cell.powerGeneration());
		}
		cargo.setEnergy(Math.min(cargo.getEnergy(), maxEnergy()));
		cargo.setEnergy(Math.max(cargo.getEnergy(), 0));
	}
	
	public int maxEnergy() {
		int capacity = 0;
		for (Cell cell : cells)
			capacity += cell.powerCapacity();
		return capacity;
	}
	
	public int housingCapacity() {
		int capacity = 0;
		for (Cell cell : cells) {
				capacity += cell.housingCapacity();
		}
		return capacity;
	}
	
	public int crewSize() {
		return crew.size();
	}
	
	public void addCrew(Crew newbie) {
		crew.add(newbie);
	}
	
	public void removeCrew(int index) {
		if(index < crew.size())
			crew.remove(index);
	}
	
	public Crew crew(int index) {
		return crew.get(index);
	}
	
	public CellType selectedType() {
		return design[cursor.getX()][cursor.getY()].getType();
	}
	
	public Cell cell(int index) {
		return cells.get(index);
	}
	
	public int cellCount() {
		return cells.size();
	}
	
	public ArrayList<Cell> cellsByType(CellType type) {
		ArrayList<Cell> selectedCells = new ArrayList<Cell>();
		
		for(Cell c : cells)
			if (c.getType().equals(type))
				selectedCells.add(c);
		
		return selectedCells;
	}
}